﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.XAPO;
using SynergyLib.DSP;
using SynergyLib.SMath;

namespace XAudio2Controls
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SchroederParams
    {
        public float CombGain { get; set; }     //<1
        public float AllpassGain { get; set; }  //<1
        public float f { get; set; } //gain factor of the direct signal
        public float DelayMs { get; set; }

    }

    /// <summary>
    /// this is currently completely broken
    /// its also made obsolete by convolution reverb/fourier stuff.
    /// 
    /// 4 parallel comb filters feeding into 2 cascading allpass filters.
    /// </summary>
    public class SchroederEffect : AudioProcessorBase<SchroederParams>
    {
        private float CombGain
        {
            get
            { return Parameters.CombGain; }
        }
        private float AllpassGain
        {
            get
            { return Parameters.AllpassGain; }
        }
        private float f
        {
            get
            {
                return Parameters.f;
            }
        }
        private float DelayMS
        {
            get
            { return Parameters.DelayMs; }
        }
        private float Delay
        {
            get {
                return 1 - DelayMS;
            }
        }

        public override void Process(BufferParameters[] inputProcessParameters, BufferParameters[] outputProcessParameters, bool isEnabled)
        {
            int frameCount = inputProcessParameters[0].ValidFrameCount;
            DataStream input = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);
            DataStream Output = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);

            
            for (int i = 0; i < frameCount; i++, Counter++)
            {
                float left = input.Read<float>();
                float right = input.Read<float>();

                float l1 = left;
                float l2 = left;
                float l3 = left;
                float l4 = left;
                float ApInput =
                    FeedbackCombFilter(l1) +
                    FeedbackCombFilter(l2) +
                    FeedbackCombFilter(l3) +
                    FeedbackCombFilter(l4);

                float ap1 = AllPassFilter(ApInput);

                float output = AllPassFilter(ap1);

                output *= f;
               
                //output = Math.ma
                
                Output.Write((float)output);
                Output.Write((float)output);
            }
        }
        private float sin_ref(int index)
        {
            return (float)Math.Sin(Trig.TwoPI * index * (Parameters.DelayMs / InputFormatLocked.SampleRate));
        }

        private float FeedbackCombFilter(float input)
        {            
            return (float)(CombGain * (input * 1 - Parameters.DelayMs));
        }

        private float AllPassFilter(float input)
        {
            return input + (input * AllpassGain) * 1- Parameters.DelayMs;
        }
    }
}
